package com.brillilab.service.core.plans.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.dao.mapper.plans.PlanMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.plans.Plan;
import com.brillilab.domain.po.plans.PlanTargetGroup;
import com.brillilab.domain.po.system.FileManage;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.vo.plans.PlanVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.plans.IPlanExperimentGroupService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.plans.IPlanTargetGroupService;
import com.brillilab.service.core.system.IFileManageService;

/**
 * <p>
 * 计划实验表 服务实现类
 * </p>
 *
 * @author zlb
 * @since 2019-09-05
 */
@Service
@Transactional
public class PlanServiceImpl implements IPlanService {

	@Resource
	private PlanMapper planMapper;
	@Resource
	private IFileManageService fileManageService;
	@Resource
	private IPlanTargetGroupService planTargetGroupService;
	@Resource
	private IPlanExperimentGroupService planExperimentGroupService;
	@Resource
	private IExperimentService experimentService;

	@Override
	public Plan insert(Plan plan) {
		int insert = planMapper.insert(plan);
		return insert == 1 ? plan : null;
	}

	@Override
	public boolean deleteById(Long id, Long labId) {
		int i = planMapper.deleteById(id);
		return i == 1 ? true : false;
	}

	@Override
	public Plan selectById(Long id) {
		return planMapper.selectById(id);
	}

	@Override
	public List<Plan> getPlanListByLabMemberIdList(List<Long> labMemberIdList, String startDate, String endDate) {
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(Plan::getLabMemberId, labMemberIdList);
		queryWrapper.ge(Plan::getPlanTime, startDate + " 00:00:00");
		queryWrapper.lt(Plan::getPlanTime, endDate);
		queryWrapper.eq(Plan::getIsDelete, BoolEnum.FALSE.getValue());
		return planMapper.selectList(queryWrapper);
	}

	@Override
	public List<Plan> getPlanList(Long labMemberId, Date startTime, Date endTime) {
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Plan::getLabMemberId, labMemberId);
		if (startTime != null)
			queryWrapper.ge(Plan::getPlanTime, DateUtil.dateString(startTime, "yyyy-MM-dd") + " 00:00:00");
		if (endTime != null)
			queryWrapper.lt(Plan::getPlanTime, DateUtil.dateString(endTime, "yyyy-MM-dd"));
		queryWrapper.eq(Plan::getIsDelete, BoolEnum.FALSE.getValue());
		return planMapper.selectList(queryWrapper);
	}

	@Override
	public List<Plan> getPlanListByTargetGroupId(Long targetGroupId) {
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Plan::getTargetGroupId, targetGroupId);
		queryWrapper.eq(Plan::getIsDelete, BoolEnum.FALSE.getValue());
		return planMapper.selectList(queryWrapper);
	}

	@Override
	public boolean updateById(Plan plan) {
		return planMapper.updateById(plan) > 0;
	}

	@Override
	public List<Plan> selectListByLabMemberId(Long labMemberId) {
		return planMapper.selectList(new LambdaQueryWrapper<Plan>().eq(Plan::getLabMemberId, labMemberId)
				.eq(Plan::getIsDelete, BoolEnum.FALSE.getValue()));
	}

	@Override
	public List<Plan> getNewPlanList(Long targetGroupId) {
		return planMapper.getNewPlanList(targetGroupId);
	}

	@Override
	public Plan getPlanByExperimentId(Long experimentId) {
		List<Plan> list = planMapper.selectList(new LambdaQueryWrapper<Plan>().eq(Plan::getExperimentId, experimentId)
				.eq(Plan::getIsDelete, BoolEnum.FALSE.getValue()));
		return CollectionUtils.isEmpty(list)?null:list.get(0);
	}

	@Override
	public List<PlanVo> getPlanVoList(Long labMemberId, String startDate, String endDate) {
		List<PlanVo> planVoList = planMapper.getPlanVoList(labMemberId, startDate, endDate);
		if (CollectionUtils.isNotEmpty(planVoList)) {
			List<Long> experimentIds = planVoList.stream().map(PlanVo::getExperimentId).collect(Collectors.toList());
			List<FileManage> analysisFiles = fileManageService.selectList(OssFileEnum.AnalyzeDataFile, experimentIds);
			if (CollectionUtils.isNotEmpty(analysisFiles)) {
				Map<Long, List<FileManage>> map = analysisFiles.stream()
						.collect(Collectors.groupingBy(FileManage::getReferDataId));
				planVoList.forEach(vo -> {
					if (CollectionUtils.isNotEmpty(map.get(vo.getExperimentId()))) {
						vo.setDataTag(BoolEnum.TRUE.getValue());
					}
				});
			}
		}
		return planVoList;
	}

	@Override
	public void deleteByExperimentGroupId(Long experimentGroupId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getExperimentGroupId, experimentGroupId));
	}

	@Override
	public void deleteByTopicExperimentId(Long topicExperimentId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getTopicExperimentId, topicExperimentId));
	}

	@Override
	public int getNoCompleteNum(Long topicTargetId) {
		return planMapper.getNoCompleteNum(topicTargetId);
	}

	@Override
	public int getMeNoCompleteNum(Long topicTargetId, Long labMemberId) {
		return planMapper.getMeNoCompleteNum(topicTargetId, labMemberId);
	}

	@Override
	public void deleteByTopicId(Long topicId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getTopicId, topicId));
	}

	@Override
	public void deleteByTopicDirectionId(Long topicDirectionId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getTopicDirectionId, topicDirectionId));
	}

	@Override
	public void deleteByTopicTargetId(Long topicTargetId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getTopicTargetId, topicTargetId));
	}

	@Override
	public void deleteByTargetGroupId(Long targetGroupId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getTargetGroupId, targetGroupId));
	}

	@Override
	public List<Plan> getTodayPlanNoCompleteList(Long labMemberId) {
		return planMapper.getTodayPlanNoCompleteList(labMemberId);
	}

	@Override
	public List<Plan> getPlanListByPlanTime(Long labMemberId, Date planTime) {
		return planMapper.getPlanListByPlanTime(labMemberId, DateUtil.dateString(planTime, "yyyy-MM-dd HH"));
	}

	@Override
	public Date getPlanTime(Long labMemberId, Date planTime, int num) {
		boolean bool = true;
		while (bool) {
			List<Plan> planList = this.getPlanListByPlanTime(labMemberId, planTime);
			if (CollectionUtils.isNotEmpty(planList)) {
				planTime = DateUtil.addHour(planTime, num);
			} else {
				bool = false;
			}
		}
		return planTime;
	}

	@Override
	public boolean isAddPlan(Long topicTargetId) {
		PlanTargetGroup targetGroup = planTargetGroupService.getNewestPlanTargetGroup(topicTargetId);
		if(targetGroup==null || targetGroup.getState().equals(2)) {
			return true;
		}
		
		List<TopicExperiment> topicExperimentList = planExperimentGroupService.getTopicExperimentList(targetGroup.getId(), null);
		if(CollectionUtils.isEmpty(topicExperimentList)) {
			return true;
		}

		List<TopicExperiment> checkList = topicExperimentList.stream().filter(te -> te.getIsCheck().equals(BoolEnum.TRUE.getValue())).collect(Collectors.toList());
		if(CollectionUtils.isNotEmpty(checkList)) {
			List<Long> experimentIds = checkList.stream().map(TopicExperiment::getExperimentId).collect(Collectors.toList());
			List<Experiment> experimentList = experimentService.selectByIdsAndNotEnd(experimentIds);
			return CollectionUtils.isEmpty(experimentList);
		}
		
		List<TopicExperiment> notCheckList = topicExperimentList.stream().filter(te -> te.getIsCheck().equals(BoolEnum.FALSE.getValue())).collect(Collectors.toList());
		if(CollectionUtils.isNotEmpty(notCheckList)) {
			List<Long> experimentIds = notCheckList.stream().map(TopicExperiment::getExperimentId).collect(Collectors.toList());
			List<Experiment> experimentList = experimentService.selectByIdsAndNotEnd(experimentIds);
			return CollectionUtils.isEmpty(experimentList);
		}
		return true;
	}

	@Override
	@SuppressWarnings("unchecked")
	public Plan getNewestPlan(Long targetGroupId) {
		LambdaQueryWrapper<Plan> queryWrapper = new LambdaQueryWrapper<Plan>();
		queryWrapper.eq(Plan::getTargetGroupId, targetGroupId);
		queryWrapper.eq(Plan::getIsDelete, BoolEnum.FALSE.getValue());
		queryWrapper.orderByDesc(Plan::getPlanTime);
		List<Plan> list = planMapper.selectList(queryWrapper);
		return CollectionUtils.isEmpty(list)?null:list.get(0);
	}

	@Override
	public void deleteByExperimentId(Long experimentId) {
		planMapper.delete(new LambdaQueryWrapper<Plan>().eq(Plan::getExperimentId, experimentId));
	}

}
